Ever wanted to make your figures more interactive?
Today we are going to talk about making interactive plots using Plotly. Plotly in a variety of programming languages, but today we will be just talking about using it in R. All of the plotly documentation can be found here.
If you have not already installed plotly, please do so here.
install.packages("plotly")
Here are some useful links to find info about using ggplotly.
ggplotly()layout()ggplotly() tooltipsBefore we start, there are two basic ways to use plot in R using plotly:
ggplotly() - this is what we will go over today because it has the same syntax as ggplot() which we have already learnedplot_ly() - there is slightly more functionality in this function, but the syntax is all new, so I’d suggest if you can do what you want with ggplotly(), do that. The syntax is not particularly hard so don’t be scared to use it if interactive plots are something you’re very interested in.When you are googling about using plotly, you will find a combination of ggplotly() and plot_ly() approaches, and some parts of the code are interchangable. The easiesy way to see which parts are, is to try.
Also note, Google gets a bit confused when googling “ggplotly” and often returns information about just ggplot, so read extra carefully when problem solving.
library(tidyverse)
## ── Attaching packages ─────────────────────────────────────── tidyverse 1.3.0 ──
## ✓ ggplot2 3.3.3 ✓ purrr 0.3.4
## ✓ tibble 3.1.0 ✓ dplyr 1.0.5
## ✓ tidyr 1.1.3 ✓ stringr 1.4.0
## ✓ readr 1.4.0 ✓ forcats 0.5.1
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## x dplyr::filter() masks stats::filter()
## x dplyr::lag() masks stats::lag()
library(plotly) # for making interactive plots
##
## Attaching package: 'plotly'
## The following object is masked from 'package:ggplot2':
##
## last_plot
## The following object is masked from 'package:stats':
##
## filter
## The following object is masked from 'package:graphics':
##
## layout
library(htmlwidgets) # for saving html files
library(palmerpenguins) # for our penguins data
Let’s look at penguins_raw this time, a df that has a bit more data than the penguins df.
head(penguins_raw)
## # A tibble: 6 x 17
## studyName `Sample Number` Species Region Island Stage `Individual ID`
## <chr> <dbl> <chr> <chr> <chr> <chr> <chr>
## 1 PAL0708 1 Adelie Pengu… Anvers Torger… Adult,… N1A1
## 2 PAL0708 2 Adelie Pengu… Anvers Torger… Adult,… N1A2
## 3 PAL0708 3 Adelie Pengu… Anvers Torger… Adult,… N2A1
## 4 PAL0708 4 Adelie Pengu… Anvers Torger… Adult,… N2A2
## 5 PAL0708 5 Adelie Pengu… Anvers Torger… Adult,… N3A1
## 6 PAL0708 6 Adelie Pengu… Anvers Torger… Adult,… N3A2
## # … with 10 more variables: Clutch Completion <chr>, Date Egg <date>,
## # Culmen Length (mm) <dbl>, Culmen Depth (mm) <dbl>,
## # Flipper Length (mm) <dbl>, Body Mass (g) <dbl>, Sex <chr>,
## # Delta 15 N (o/oo) <dbl>, Delta 13 C (o/oo) <dbl>, Comments <chr>
head(penguins)
## # A tibble: 6 x 8
## species island bill_length_mm bill_depth_mm flipper_length_… body_mass_g sex
## <fct> <fct> <dbl> <dbl> <int> <int> <fct>
## 1 Adelie Torge… 39.1 18.7 181 3750 male
## 2 Adelie Torge… 39.5 17.4 186 3800 fema…
## 3 Adelie Torge… 40.3 18 195 3250 fema…
## 4 Adelie Torge… NA NA NA NA <NA>
## 5 Adelie Torge… 36.7 19.3 193 3450 fema…
## 6 Adelie Torge… 39.3 20.6 190 3650 male
## # … with 1 more variable: year <int>
bill_depth_length <- penguins_raw %>%
ggplot(aes(x = `Culmen Length (mm)`, y = `Culmen Depth (mm)`)) +
geom_point()
bill_depth_length
## Warning: Removed 2 rows containing missing values (geom_point).
Making plot interactive.
You can learn more about the ggplotly() function, including its arguments here.
ggplotly(bill_depth_length)
Wow. That was easy!
Adding a title, and changing the theme.
bill_depth_length <- penguins_raw %>%
ggplot(aes(x = `Culmen Length (mm)`, y = `Culmen Depth (mm)`)) +
geom_point() +
theme_minimal() +
labs(title = "Understanding Penguin Bill Dimensions")
ggplotly(bill_depth_length)
What if we want to hover over each point and be able to tell which Island the penguin was found on?
bill_depth_length <- penguins_raw %>%
ggplot(aes(x = `Culmen Length (mm)`, y = `Culmen Depth (mm)`,
text = Island)) +
geom_point() +
theme_minimal() +
labs(title = "Understanding Penguin Bill Dimensions")
ggplotly(bill_depth_length,
tooltip = "text")
To be able to hover with a variable, it has to be indicated someplace in your ggplot2 call.
bill_depth_length <- penguins_raw %>%
ggplot(aes(x = `Culmen Length (mm)`, y = `Culmen Depth (mm)`,
text = Island, group = `Individual ID`)) +
geom_point() +
theme_minimal() +
labs(title = "Understanding Penguin Bill Dimensions")
ggplotly(bill_depth_length,
tooltip = c("text", "Individual ID")) # hover test will be in this order
You can use paste to add some information you’d like to see in each of the hover texts, here, we are indicating Island: Island
bill_depth_length <- penguins_raw %>%
ggplot(aes(x = `Culmen Length (mm)`, y = `Culmen Depth (mm)`,
text = paste("Island:", Island))) +
geom_point() +
theme_minimal() +
labs(title = "Understanding Penguin Bill Dimensions")
ggplotly(bill_depth_length,
tooltip = "text")
Changing hover label aesthetics and the fonts of your plot.
# setting fonts for the plot
font <- list(
family = "Roboto Condensed",
size = 15,
color = "white")
# setting hover label specs
label <- list(
bgcolor = "#FF0000",
bordercolor = "transparent",
font = font) # we can do this bc we already set font
# plotting like normal
bill_depth_length <- penguins_raw %>%
ggplot(aes(x = `Culmen Length (mm)`, y = `Culmen Depth (mm)`,
text = paste("Island:", Island))) +
geom_point() +
theme_minimal() +
labs(title = "A Deep Dive (ha) Into \nUnderstanding Penguin Bill Dimensions")
# use\n to bring your text to another line
# amending our ggplotly call to include new fonts and hover label specs
ggplotly(bill_depth_length, tooltip = "text") %>%
style(hoverlabel = label) %>%
layout(font = font)
Keep your axis labels so when you zoom, you can see where you are on your plot.
ggplotly(bill_depth_length,
tooltip = "text",
dynamicTicks = TRUE)
Don’t forget you can use things like faceting, that we have gone over previously in Session 10.
bill_depth_length <- penguins %>%
ggplot(aes(x = bill_length_mm, y = bill_depth_mm, color = species,
text = paste("Island:", island))) +
geom_point() +
theme_minimal() +
theme(legend.position = "none") +
labs(title = "Understanding Penguin Bill Dimensions",
x = "Culmen Bill Length (mm)",
y = "Culmen Bill Depth (mm)") +
facet_wrap(~species)
ggplotly(bill_depth_length,
tooltip = "text")
Add frame in your aesthetics mapping to tell plotly what column to animate over.
# add frame
bill_depth_length <- penguins_raw %>%
ggplot(aes(x = `Culmen Length (mm)`, y = `Culmen Depth (mm)`,
frame = Island, text = `Individual ID`)) +
geom_point() +
theme_minimal() +
labs(title = "Understanding Penguin Bill Dimensions")
ggplotly(bill_depth_length,
tooltip = "text")
Assign the plot you want to save to an object, and use the function saveWidget() to save it. You can find the documentation here.
# assign ggplotly plot to an object
ggplotly_to_save <- ggplotly(bill_depth_length,
tooltip = "text")
# save
saveWidget(widget = ggplotly_to_save,
file = "ggplotlying.html")
Back to birds. Let’s re-create the birds joined dataset from the end of Session 3 on joining.
# create directory for data to go
dir.create('data/birds/', recursive = TRUE)
## Warning in dir.create("data/birds/", recursive = TRUE): 'data/birds' already
## exists
# preparing to download
# denote bird file url
birds_url <-
'https://raw.githubusercontent.com/biodash/biodash.github.io/master/assets/data/birds/backyard-birds_Ohio.tsv'
# denote file name
birds_file <- 'data/birds/backyard-birds_Ohio.tsv'
# get file
download.file(url = birds_url,
destfile = birds_file)
# read in birds data
birds <- read_tsv(file = 'data/birds/backyard-birds_Ohio.tsv')
##
## ── Column specification ────────────────────────────────────────────────────────
## cols(
## class = col_character(),
## order = col_character(),
## family = col_character(),
## genus = col_character(),
## species = col_character(),
## locality = col_character(),
## stateProvince = col_character(),
## decimalLatitude = col_double(),
## decimalLongitude = col_double(),
## eventDate = col_datetime(format = ""),
## species_en = col_character(),
## range = col_character()
## )
Look at your new df.
head(birds)
## # A tibble: 6 x 12
## class order family genus species locality stateProvince decimalLatitude
## <chr> <chr> <chr> <chr> <chr> <chr> <chr> <dbl>
## 1 Aves Passer… Corvid… Cyano… Cyanocit… 44805 As… Ohio 40.9
## 2 Aves Passer… Corvid… Cyano… Cyanocit… 45244 Ci… Ohio 39.1
## 3 Aves Passer… Corvid… Cyano… Cyanocit… 44132 Eu… Ohio 41.6
## 4 Aves Passer… Corvid… Cyano… Cyanocit… 45242 Ci… Ohio 39.2
## 5 Aves Passer… Corvid… Cyano… Cyanocit… 45246 Ci… Ohio 39.3
## 6 Aves Passer… Corvid… Cyano… Cyanocit… 44484 Wa… Ohio 41.2
## # … with 4 more variables: decimalLongitude <dbl>, eventDate <dttm>,
## # species_en <chr>, range <chr>
dim(birds)
## [1] 311441 12
Filter your new birds df to only inclue Blue Jays. Check to see how many Blue Jay sightings there were in Ohio.
Create a map that plots all the Blue Jays found around Ohio. Color the points blue. Make sure the aspect ratio of Ohio looks reasonable to you.
Make your plot interactive so you can hover and and see the locality of each bald eagle observation.
Change the hover text so that the background color is red, clean up your axis labels, and make all the fonts for the plot Arial.
Let’s go back to the Gapminder data we looked at in the instructional part of Session 10 on faceting, animating, and multi-plotting.
# install.packages("gapminder") # if you weren't at Session 10
library(gapminder)
head(gapminder)
## # A tibble: 6 x 6
## country continent year lifeExp pop gdpPercap
## <fct> <fct> <int> <dbl> <int> <dbl>
## 1 Afghanistan Asia 1952 28.8 8425333 779.
## 2 Afghanistan Asia 1957 30.3 9240934 821.
## 3 Afghanistan Asia 1962 32.0 10267083 853.
## 4 Afghanistan Asia 1967 34.0 11537966 836.
## 5 Afghanistan Asia 1972 36.1 13079460 740.
## 6 Afghanistan Asia 1977 38.4 14880372 786.
Make a bubble-style plot that shows the life expectancy vs. GDP per capita over 1952 to 2007 for all countries. Color by continent, and indicate population by size. Use your knowledge of making plots to alter it such that you think it is descriptive and aesthetic.